using System.Collections;  // 引用用于协程的命名空间
using System.Collections.Generic;  // 引用用于列表操作的命名空间
using UnityEngine;  // 引用Unity引擎的核心功能
using UnityEngine.Audio;  // 引用音频功能
using UnityEngine.UI;  // 引用UI组件，比如Text, Button等

/// <summary>
/// 实现语音识别处理
/// </summary>
public class RTSpeechHandler : MonoBehaviour
{
    /// <summary>
    /// 麦克风名称
    /// </summary>
    public string m_MicrophoneName = null;

    /// <summary>
    /// 设置为静音阈值，低于此值视为无声音
    /// </summary>
    public float m_SilenceThreshold = 0.01f;

    /// <summary>
    /// 录音最大时长（秒）
    /// </summary>
    [Header("录音时长限制（秒）")]
    public float m_RecordingTimeLimit = 2.0f;

    /// <summary>
    /// 从语音唤醒到进入听音状态的最大时长（秒）
    /// </summary>
    [Header("语音唤醒后听音等待时长")]
    public float m_LossAwakeTimeLimit = 10f;

    /// <summary>
    /// 锁定状态，用于防止多次进入录音状态
    /// </summary>
    [SerializeField]private bool m_LockState = false;

    /// <summary>
    /// 存储录音数据
    /// </summary>
    private AudioClip m_RecordedClip;

    /// <summary>
    /// 唤醒关键字
    /// </summary>
    [SerializeField]private string m_AwakeKeyWord = string.Empty;

    /// <summary>
    /// 唤醒状态
    /// </summary>
    [Header("是否处于语音唤醒状态")]
    [SerializeField]private bool m_AwakeState = false;

    /// <summary>
    /// 听音状态
    /// </summary>
    [SerializeField] private bool m_ListeningState = false;

    /// <summary>
    /// 录音状态
    /// </summary>
    [SerializeField] private bool m_IsRecording = false;

    /// <summary>
    /// 无声计时器
    /// </summary>
    [SerializeField]private float m_SilenceTimer = 0.0f;

    /// <summary>
    /// 聊天样本
    /// </summary>
    [SerializeField]private RTChatSample m_ChatSample;

    /// <summary>
    /// 语音唤醒模块
    /// </summary>
    [SerializeField] private WOV m_VoiceAWake;

    private void Awake()
    {
        OnInit();  // 初始化设置
    }

    private void OnInit()
    {
        // 绑定AI回复完成后的回调
        m_ChatSample.OnAISpeakDone += SpeachDoneCallBack;

        // 绑定语音唤醒的回调
        m_VoiceAWake.OnBindAwakeCallBack(AwakeCallBack);
    }

    private void Start()
    {
        if (m_MicrophoneName == null)
        {
            // 如果没有指定麦克风，使用系统默认麦克风
            m_MicrophoneName = Microphone.devices[0];
        }

        // 如果正在录音，则停止之前的录音
        if (Microphone.IsRecording(m_MicrophoneName))
        {
            Microphone.End(m_MicrophoneName);
        }

        // 开始新的录音
        m_RecordedClip = Microphone.Start(m_MicrophoneName, false, 30, 16000);

        // 等待麦克风开始录音
        while (Microphone.GetPosition(null) <= 0) { }

        // 启动检测录音的协程
        StartCoroutine(DetectRecording());
    }

    /// <summary>
    /// 检测录音中的音量变化
    /// </summary>
    private IEnumerator DetectRecording()
    {
        while (true)
        {
            float[] samples = new float[128];  // 存储录音数据的数组
            int position = Microphone.GetPosition(null);
            if (position < samples.Length)
            {
                yield return null;
                continue;
            }

            // 从录音剪辑中获取数据
            try { m_RecordedClip.GetData(samples, position - samples.Length); } catch { }

            float rms = 0.0f;
            foreach (float sample in samples)
            {
                rms += sample * sample;  // 计算均方根值
            }

            rms = Mathf.Sqrt(rms / samples.Length);  // 获取音量值

            if (rms > m_SilenceThreshold)
            {
                m_SilenceTimer = 0.0f;  // 重置无声计时器

                // 如果当前不是在唤醒状态，也不是在监听状态，开始语音监听
                if (!m_AwakeState && !m_ListeningState)
                {
                    StartVoiceListening();
                }

                // 如果当前是唤醒状态且没有开始录音，开始录音
                if (m_AwakeState && !m_IsRecording)
                {
                    StartRecording();
                }

            }
            else
            {
                // 如果没有锁定状态，增加无声计时器
                if (!m_LockState)
                {
                    m_SilenceTimer += Time.deltaTime;
                }

                // 如果处于监听状态并且没有唤醒状态，且无声超过设定时间，停止语音监听
                if (m_ListeningState && !m_AwakeState && m_SilenceTimer >= m_RecordingTimeLimit)
                {
                    StopVoiceListening();
                }

                // 如果处于唤醒状态并且正在录音，且无声超过设定时间，停止录音
                if (m_AwakeState && m_IsRecording && m_SilenceTimer >= m_RecordingTimeLimit)
                {
                    StopRecording();
                }

                // 如果处于唤醒状态且没有录音，并且无声超过设定时间，认为失去唤醒状态
                if (m_AwakeState && !m_IsRecording && m_SilenceTimer >= m_LossAwakeTimeLimit)
                {
                    m_AwakeState = false;
                    PrintLog("Loss->语音唤醒失效");
                }
            }

            yield return null;
        }
    }

    [SerializeField]private AudioSource m_Greeting;
    [SerializeField] private AudioClip m_GreatingVoice;

    /// <summary>
    /// 语音唤醒回调，检查唤醒词是否匹配
    /// </summary>
    private void AwakeCallBack(string _msg)
    {
        if (_msg == m_AwakeKeyWord && !m_AwakeState)
        {
            m_AwakeState = true;  // 设置为唤醒状态
            Debug.Log("识别到唤醒词：" + _msg);
            PrintLog("Link->开始语音识别");

            // 播放问候语音
            if (m_Greeting)
            {
                m_Greeting.clip = m_GreatingVoice;
                m_Greeting.Play();
            }
        }
    }

    /// <summary>
    /// 启动语音监听
    /// </summary>
    private void StartVoiceListening()
    {
        m_ListeningState = true;
        m_VoiceAWake.StartRecognizer();  // 启动语音识别器
        PrintLog("开始->语音识别启动");
    }

    /// <summary>
    /// 停止语音监听
    /// </summary>
    private void StopVoiceListening()
    {
        m_ListeningState = false;
        m_VoiceAWake.StopRecognizer();  // 停止语音识别器
        PrintLog("结束->停止语音识别");
    }

    /// <summary>
    /// 启动录音
    /// </summary>
    private void StartRecording()
    {
        m_SilenceTimer = 0.0f;  // 重置无声计时器
        m_IsRecording = true;  // 设置为录音状态
        PrintLog("开始录音...");

        // 停止旧的录音，开始新的录音
        Microphone.End(m_MicrophoneName);
        m_RecordedClip = Microphone.Start(m_MicrophoneName, false, 30, 16000);
    }

    /// <summary>
    /// 停止录音
    /// </summary>
    private void StopRecording()
    {
        m_IsRecording = false;
        PrintLog("停止录音...");

        // 停止麦克风录音
        Microphone.End(m_MicrophoneName);

        // 处理录音数据
        SetRecordedAudio();
    }

    /// <summary>
    /// 重新开始录音
    /// </summary>
    public void ReStartRecord()
    {
        m_RecordedClip = Microphone.Start(m_MicrophoneName, true, 30, 16000);  // 开始新的录音
        m_LockState = false;  // 解除锁定状态
    }

    private void SetRecordedAudio()
    {
        m_LockState = true;  // 锁定状态，防止多次调用

        // 将录音数据传递给聊天系统进行处理
        m_ChatSample.AcceptClip(m_RecordedClip);
    }

    /// <summary>
    /// AI回复完成后的回调，重新开始录音
    /// </summary>
    private void SpeachDoneCallBack()
    {
        ReStartRecord();  // 重新开始录音
    }

    [SerializeField] private Text m_PrintText;

    /// <summary>
    /// 打印日志信息
    /// </summary>
    private void PrintLog(string _log)
    {
        m_PrintText.text = _log;  // 将日志信息显示到文本框中
    }

}